package ferp.android.tasks.local;

import android.os.AsyncTask;
import ferp.android.activities.Ferp;
import ferp.android.services.IResolverService2;
import ferp.android.services.ServiceException;
import ferp.android.services.ServiceProxy;
import ferp.core.ai.tree2.Evaluator;
import ferp.core.ai.tree2.Score;
import ferp.core.card.Card;
import ferp.core.game.Game;
import ferp.core.game.Levels;
import ferp.core.game.Settings;
import ferp.core.game.Trick;
import ferp.core.player.Hand;

/**
 * User: olegs
 * Date: 4/3/13 6:44 PM
 */
public class TaskFastMoving extends AsyncTask<Void, Void, ServiceException>
{
  public TaskFastMoving(Ferp ferp, Game game, Settings settings, IResolverService2 service)
  {
    this.ferp     = ferp;
    this.game     = game;
    this.settings = settings;
    this.service  = service;

    game.player.starting = Game.next(game.player.dealer);
    game.rounds = 0;
    game.trash = 0;

    for (int i = 0; i < Game.PLAYERS; ++i)
      game.setTricks(i, 0);
  }

  @Override
  protected void onPreExecute()
  {
    ferp.onFastMovingStarted(game);
  }

  @Override
  protected ServiceException doInBackground(Void... voids)
  {
    try
    {
      int drop = game.getDropHash(0) | game.getDropHash(1);

      ServiceProxy.initialize(service, game.getDeclarerBid().current.isMisere() ? Evaluator.MISERE : Evaluator.TRICKING,
                              game.player.declarer, game.player.starting, game.trump().ordinal(),
                              game.getHand(0).current, game.getHand(1).current, game.getHand(2).current,
                              game.getTalonCompressed(0), game.getTalonCompressed(1),
                              drop, drop, game.rounds, true, settings.isRostov(), game.service);

      solve();

      return null;
    }
    catch (ServiceException e)
    {
      return e;
    }
  }

  @Override
  protected void onPostExecute(ServiceException e)
  {
    if (e == null)
    {
      // switch to Score state
      game.options.clear();
      game.score();

      ferp.onFastMovingFinished(game);
    }
    else
      ferp.exit(e);
  }

  private void solve() throws ServiceException
  {
    boolean complete = false;

    while (!complete)
    {
      game.hand = 0;

      // make moves
      for (int id = game.player.starting; Trick.size(game.trick.current) < Game.PLAYERS; id = Game.next(id), ++game.hand)
      {
        ServiceProxy.solve(service);

        int score = ServiceProxy.getBestScore(service);

        game.options.score = (short)score;

        // make the move according to AI level
        int depth = Levels.getBestMoveDepth(game, settings, id == game.player.declarer ? game.declarer() : game.opponent());
        Game.HandData hand = game.getHand(id);
        byte move = ServiceProxy.getBestMove(service, depth, game.hand, game.trick.current, hand.current);

        // update current player's hand and game trick
        hand.current = Hand.remove(hand.current, Card.card(move).hash);
        game.trick.current = Trick.add(game.trick.current, id, move);

        // advance
        ServiceProxy.advance(service, game.hand, game.trick.current);
      }

      complete = Score.isComplete(game.options.score);

      if (complete)
      {
        // tree is complete - finalize tricks
        for (int id = 0; id < Game.PLAYERS; ++id)
          game.addTricks(id, Score.get(game.options.score, id));
      }
      else
      {
        game.player.starting = Trick.winner(game.trick.current, game.trump());
        game.addTricks(game.player.starting, 1);
        game.trash = game.trick.trash(game.trash);
      }
    }
  }

  private Ferp ferp;
  private Game game;
  private Settings settings;
  private IResolverService2 service;
}
